package com.bicon.botu.account.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bicon.botu.account.common.AccountConstants;
import com.bicon.botu.account.common.utils.Encrypt;
import com.bicon.botu.account.dto.AccountInfoDTO;
import com.bicon.botu.account.dto.AccountParam;
import com.bicon.botu.account.dto.RoleDto;
import com.bicon.botu.account.dto.UserInfoParam;
import com.bicon.botu.account.entity.*;
import com.bicon.botu.account.handler.AccountHandler;
import com.bicon.botu.account.mapper.AccountInfoMapper;
import com.bicon.botu.account.mapper.AccountRoleMapper;
import com.bicon.botu.account.param.RegisterParam;
import com.bicon.botu.account.service.AccountThirdService;
import com.bicon.botu.account.service.IAccountService;
import com.bicon.botu.account.service.IUserInfoService;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.entity.BaseResult;
import com.bicon.botu.core.base.common.utils.EncryptionUtil;
import com.bicon.botu.core.base.common.utils.IdGenerator;
import com.bicon.botu.core.base.common.utils.StringUtils;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.third.provider.rpc.service.MessageRpcService;
import com.bicon.botu.third.service.MessageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

import static com.baomidou.mybatisplus.toolkit.StringUtils.checkValNull;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isNotEmpty;

/**
 * 账户业务处理类
 *
 * @author liushujie
 * @date 2018/07/11 11:01
 */
@Slf4j
@Service
public class AccountServiceImpl extends ServiceImpl<AccountInfoMapper, AccountInfo> implements IAccountService {

    /**
     * 第三方服务，短信发送
     */
    @Autowired
    MessageRpcService thirdService;

    @Autowired
    MessageService messageService;

    @Autowired
    private AccountHandler accountHandler;

    @Autowired
    private RedisHandler redisHandler;

    @Autowired
    private AccountRoleMapper accountRoleMapper;

    @Autowired
    private AccountThirdService accountThirdService;

    @Autowired
    private IUserInfoService userInfoService;
    /**
     * 发送短信验证码
     *
     * @param phone 手机号
     * @return true发送成功、false 发送失败
     */
    @Override
    public boolean sendSmsCode(String phone, Integer type) {
        //六位随机码
        String code = IdGenerator.createXCode(6);
        //第三方服务发送
        BaseResult resultJson = thirdService.sendYunSms(phone, code, null);
        //json解析返回值
//        BaseResult entity = JsonUtil.fromJson(resultJson, BaseResult.class);
        if (resultJson != null) {
            if (resultJson.getCode() == Constants.RESPONSE_CODE_200) {
                //发送成功 需要缓存到redis
                IdentifyingCode identifyingCode = new IdentifyingCode();
                String sendCode = redisHandler.getGlobalRedisTemplate().getStringValue(AccountConstants.REDISPREFIX_CODE, phone + type.toString());
                if (!isEmpty(sendCode)) {
                    identifyingCode = JSONObject.parseObject(sendCode, IdentifyingCode.class);
                } else {
                    identifyingCode.setCount(0);
                }
                Date date = new Date();
                identifyingCode.setAccount(phone);
                identifyingCode.setCode(code);
                identifyingCode.setCreateTime(date);
                identifyingCode.setUpdateTime(date);
                identifyingCode.setCount(identifyingCode.getCount() + 1);
                redisHandler.getGlobalRedisTemplate().cacheStringValue(AccountConstants.REDISPREFIX_CODE, phone + type.toString(), JSON.toJSONString(identifyingCode), AccountConstants.CODE_EXPIRE_TIME);
                return true;
            }
            //失败
            return false;
        }
        //失败
        return false;
    }

    /**
     * 生产验证码并返回，测试用
     *
     * @param phone
     * @param type
     * @return
     */
    @Override
    public String sendSmsCodeString(String phone, Integer type) {
        //六位随机码
        String code = IdGenerator.createXCode(6);
        //发送成功 需要缓存到redis
        IdentifyingCode identifyingCode = new IdentifyingCode();
        String sendCode = redisHandler.getGlobalRedisTemplate().getStringValue(AccountConstants.REDISPREFIX_CODE, phone + type.toString());
        if (!isEmpty(sendCode)) {
            identifyingCode = JSONObject.parseObject(sendCode, IdentifyingCode.class);
        } else {
            identifyingCode.setCount(0);
        }
        Date date = new Date();
        identifyingCode.setAccount(phone);
        identifyingCode.setCode(code);
        identifyingCode.setCreateTime(date);
        identifyingCode.setUpdateTime(date);
        identifyingCode.setCount(identifyingCode.getCount() + 1);
        redisHandler.getGlobalRedisTemplate().cacheStringValue(AccountConstants.REDISPREFIX_CODE, phone + type.toString(), JSON.toJSONString(identifyingCode), AccountConstants.CODE_EXPIRE_TIME);
        return code;
    }

    /**
     * 校验验证码
     *
     * @param phone 手机号
     * @param code  验证码
     * @return true验证成功、false 验证失败
     */
    @Override
    public boolean verifySmsCode(String phone, String code, Integer type) {
        //根据缓存获取验证码
        String sendCode = redisHandler.getGlobalRedisTemplate().getStringValue(AccountConstants.REDISPREFIX_CODE, phone + type.toString());
        if (isEmpty(sendCode)) {
            return false;
        }
        IdentifyingCode identifyingCode = JSONObject.parseObject(sendCode, IdentifyingCode.class);
        if (!identifyingCode.getCode().equals(code)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 校验账户有没有被注册
     *
     * @param account 账号
     * @param type    操作类型（1移动端、2商户端、3平台端）
     * @return
     */
    @Override
    public boolean checkAccount(String account, Integer type) {
        return false;
    }

    /**
     * web 后台用户登录
     *
     * @param account  账号
     * @param password 密码
     * @param type     登录类型
     * @return
     */
    @Override
    public String manageLogin(String account, String password, Integer type) {
        return null;
    }

    /**
     * 账号详情
     *
     * @param account 账号
     * @param type    登录类型（1：客户端，2：商家，3：平台）
     * @return
     */
    @Override
    public AccountInfoDTO detail(String account, Integer type) {
        AccountInfoDTO accountInfoDTO = new AccountInfoDTO();
        AccountInfo accounts = new AccountInfo().selectOne(new EntityWrapper<AccountInfo>().eq(AccountConstants.ACCOUNT_FIELD, account).eq("type", type).eq("logic_delete", AccountConstants.DEL_LOGIC_NORMAL));
        if (null != accounts) {
            BeanUtils.copyProperties(accounts, accountInfoDTO);
            return accountInfoDTO;
        }
        return null;
    }

    /**
     * 账号详情
     * @param userId
     * @param type
     * @return
     */
    @Override
    public AccountInfoDTO detailInfo(String userId, Integer type) {
        AccountInfoDTO accountInfoDTO = new AccountInfoDTO();
        AccountInfo accounts = new AccountInfo().selectOne(new EntityWrapper<AccountInfo>().eq("id", userId).eq("type", type).eq("logic_delete", AccountConstants.DEL_LOGIC_NORMAL));
        if (null != accounts) {
            BeanUtils.copyProperties(accounts, accountInfoDTO);
            return accountInfoDTO;
        }
        return null;
    }

    /**
     * 第三方账号获取账户信息
     *
     * @param thirdId
     * @param thirdParty
     * @return
     */
    @Override
    public AccountInfoDTO thirdAccout(String thirdId, Integer thirdParty) {
        AccountInfoDTO accountInfoDTO = new AccountInfoDTO();
        AccountInfo accounts = new AccountInfo().selectOne(new EntityWrapper<AccountInfo>().eq("third_id", thirdId).eq("third_party", thirdParty).eq("type", 1).eq("logic_delete", AccountConstants.DEL_LOGIC_NORMAL));
        BeanUtils.copyProperties(accounts, accountInfoDTO);
        return accountInfoDTO;
    }

    /**
     * APP用户注册
     *
     * @return 返回token
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AccountInfoDTO register(String account, String password, String thirdId, Integer thirdParty, Integer source) {

        AccountInfo accountInfo = new AccountInfo();
        accountInfo.preInsert();
        String token = IdGenerator.create24Id();
        accountInfo.setAccount(account);
        accountInfo.setSalt(Encrypt.generateSalt(10));
        accountInfo.setPassword(Encrypt.md5ForAuth(password, accountInfo.getSalt()));
        accountInfo.setEnable(AccountConstants.ENABLE_TRUE);
        accountInfo.setSource(source);
        //客户端
        accountInfo.setType(1);
//        //第三方信息填充关联
//        if (isNotEmpty(thirdId)) {
//            accountInfo.setThirdId(thirdId);
//        }
//        if (thirdParty != null) {
//            accountInfo.setThirdParty(thirdParty);
//        }
        if (accountInfo.insert()) {
            accountHandler.saveAccount(accountInfo);
            UserInfoParam userInfoParam = new UserInfoParam();
            userInfoParam.setId(accountInfo.getId());
            userInfoParam.setNick("新用户"+account.substring(account.length()-6,account.length()));
            userInfoParam.setName(accountInfo.getAccount());
            userInfoParam.setPhone(accountInfo.getAccount());
            //创建账号
            userInfoService.createUserInfo(userInfoParam);
        }
        return new AccountInfoDTO(accountInfo.getAccount(), token, accountInfo.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AccountInfoDTO registerBind(RegisterParam registerParam) {
        AccountInfoDTO accountInfoDTO =this.detail(registerParam.getAccount(), 1);
        String account = registerParam.getAccount();
        if(null == accountInfoDTO){
            //创建账号
            AccountInfo accountInfo = new AccountInfo();
            accountInfo.preInsert();
            accountInfo.setAccount(account);
            accountInfo.setSalt(Encrypt.generateSalt(10));
            accountInfo.setPassword(Encrypt.md5ForAuth("1234567890", accountInfo.getSalt()));
            accountInfo.setEnable(AccountConstants.ENABLE_TRUE);
            accountInfo.setSource(registerParam.getSource());
            accountInfo.insert();

            //添加用户信息
            UserInfoParam userInfoParam = new UserInfoParam();
            userInfoParam.setId(accountInfo.getId());
            userInfoParam.setName(accountInfo.getAccount());
            userInfoParam.setPhone(accountInfo.getAccount());
            userInfoParam.setNick(registerParam.getNick());
            userInfoParam.setGender(registerParam.getGender());
            userInfoParam.setLargeImg(registerParam.getLargeImg().trim());
            userInfoParam.setSmallImg(registerParam.getSmallImg().trim());
            userInfoService.createUserInfo(userInfoParam);

            if(StringUtils.isEmpty(registerParam.getNick())){
                userInfoParam.setNick("新用户"+account.substring(account.length()-6,account.length()));
            }
            if(StringUtils.isEmpty(registerParam.getLargeImg().trim())){
                userInfoParam.setLargeImg(null);
            }
            if(StringUtils.isEmpty(registerParam.getSmallImg().trim())){
                userInfoParam.setSmallImg(null);
            }
            //更新信息到缓存
            accountHandler.saveAccount(accountInfo);
            String token = IdGenerator.create24Id();
            accountInfoDTO =  new AccountInfoDTO(accountInfo.getAccount(), token, accountInfo.getId());
        }
        //添加第三方账号
        AccountThird accountThird = new AccountThird();
        accountThird.setThirdId(registerParam.getThirdId());
        accountThird.setThirdParty(registerParam.getThirdParty());
        accountThird.setAccountId(accountInfoDTO.getId());
        accountThird.setType(1);
        accountThird.setSource(registerParam.getSource());
        accountThird.preInsert();
        accountThirdService.insert(accountThird);

        accountInfoDTO.setThirdId(registerParam.getThirdId());
        accountInfoDTO.setThirdParty(registerParam.getThirdParty());
        return accountInfoDTO;
    }

    /**
     * APP用户登录
     *
     * @param accountParam
     * @return
     */
    @Override
    public String login(AccountParam accountParam) {
        return null;
    }

    /**
     * 快捷登录 手机号、验证码登录
     *
     * @param accountParam
     * @return
     */
    @Override
    public String phoneLogin(AccountParam accountParam) {
        return null;
    }


    /**
     * 忘记密码：后台，通过账号和手机号验证码修改密码
     *
     * @param account  账号
     * @param password 密码
     * @param type     登录类型（1：客户端，2：商家，3：平台）
     * @return
     */
    @Override
    public boolean forgetPassByAccout(String account, String password, Integer type) {
        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setPassword(password);
        accountInfo.preUpdate();
        return accountInfo.update(new EntityWrapper<AccountInfo>().eq(AccountConstants.ACCOUNT_FIELD, account).eq("type", type));
    }

    /**
     * 检查账号和手机号是否匹配存在
     *
     * @param account 账号
     * @param type    登录类型（1：客户端，2：商家，3：平台）
     * @return
     */
    @Override
    public boolean checkAccountExist(String account, Integer type) {
        AccountInfo accountInfo = new AccountInfo().selectOne(new EntityWrapper<AccountInfo>().eq("account", account).eq("type", type).eq("logic_delete", AccountConstants.DEL_LOGIC_NORMAL));
        if (accountInfo != null) {
            return true;
        }
        return false;
    }

    /**
     * 获取用户角色列表
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public BaseResult getAccountRole(String userId) {
//      校验用户是否存在角色
        if (redisHandler.getGlobalRedisTemplate().hasKey(AccountConstants.ACCOUNT_ROLE + userId)) {
//          获取用户角色列表
            List<String> list = redisHandler.getGlobalRedisTemplate().getList(AccountConstants.ACCOUNT_ROLE, userId);
            List<Role> roles = new ArrayList<>();
            for (String roleId : list) {
                Role role = new Role();
                role.setId(roleId);
                role.setType("0");
                role.setLogicDelete(Constants.DEL_LOGIC_NORMAL);
                role = role.selectById();
                roles.add(role);
            }
            return new BaseResult(Constants.RESPONSE_CODE_200, Constants.RESPONSE_MESSAGE_200, roles);
        }
        return new BaseResult(Constants.RESPONSE_CODE_200, Constants.RESPONSE_MESSAGE_200);
    }

    /**
     * 分页查询账户列表
     *
     * @param pageNo   页码
     * @param pageSize 每页显示数量
     * @param type     登录类型（1移动端、2商户端、3平台端）
     * @return
     */
    @Override
    public Page<AccountInfoDTO> selectAccounts(int pageNo, int pageSize, Integer type) {
        Page<AccountInfo> accountPage = new AccountInfo().selectPage(new Page<>(pageNo, pageSize), new EntityWrapper<AccountInfo>().eq("type", type).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Page<AccountInfoDTO> accountInfoDTOPage = new Page<AccountInfoDTO>();
        if (null != accountPage) {
            BeanUtils.copyProperties(accountPage, accountInfoDTOPage);
            return accountInfoDTOPage;
        }
        return accountInfoDTOPage;
    }

    /**
     * 更新Account状态
     *
     * @param id     账号id
     * @param enable 是否启用0:启用、1：禁用
     * @return
     */
    @Override
    public boolean updateAccountState(String id, Integer enable) {
        AccountInfo account = new AccountInfo();
        account.preUpdate();
        account.setEnable(enable);
        account.setId(id);
        boolean result = account.updateById();
        if (result) {
            //更新redis缓存
            account = account.selectById();
            if (!checkValNull(account)) {
                accountHandler.saveAccount(account);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 新增后台账号
     *
     * @param account  登录账号
     * @param password 登录密码
     * @param enable   类型：0：正常、1：禁用状态
     * @param type     登录类型（1移动端、2商户端、3平台端）
     * @return
     */
    @Override
    public boolean saveAccount(String account, String password, Integer enable, Integer type) {
        AccountInfo resultAccount = new AccountInfo();
        resultAccount.setSalt(Encrypt.generateSalt(10));
        if (password != null && !"".equals(password)) {
            resultAccount.setPassword(Encrypt.md5ForAuth(password, resultAccount.getSalt()));
        }
        resultAccount.setAccount(account);
        resultAccount.setEnable(enable);
        resultAccount.setType(type);
        resultAccount.preInsert();
        return resultAccount.insert();
    }

    /**
     * 更新账户信息
     *
     * @param id       账号id
     * @param account  账号
     * @param password 密码
     * @param type     登录类型（1移动端、2商户端、3平台端）
     * @return
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(String id, String account, String password, Integer type) {
        AccountInfo preAccount = new AccountInfo();
        preAccount.setId(id);
        preAccount = preAccount.selectById();
        preAccount.preUpdate();
        if (password != null && !password.equals("")) {
            preAccount.setPassword(Encrypt.md5ForAuth(password, preAccount.getSalt()));
        }
        preAccount.setAccount(account);
        boolean result = preAccount.updateById();

        //修改个资料  根据userID修改手机号
        UserInfoParam userInfoParam = new UserInfoParam();
        userInfoParam.setId(id);
        userInfoParam.setPhone(account);
        userInfoService.updateUserInfo(userInfoParam);

        return result;
    }

    /**
     * 初始化app用户缓存
     *
     * @return
     */
    @Override
    public boolean initAccount() {
        List<AccountInfo> accounts = new AccountInfo().selectList(new EntityWrapper<AccountInfo>().eq("type", 1).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        if (!CollectionUtils.isEmpty(accounts)) {
            for (AccountInfo account : accounts) {
                account.setPassword("");
                redisHandler.getGlobalRedisTemplate().remove(Constants.BUTO_USER_ACCOUNT, account.getId());
                redisHandler.getGlobalRedisTemplate().cacheStringValue(Constants.BUTO_USER_ACCOUNT, account.getId(), JSONObject.toJSON(account).toString());
            }
        }
        return true;
    }

    /**
     * 后台添加用户及角色
     *
     * @param account  账户
     * @param code     角色code
     * @param password 密码
     * @return
     */
    @Override
    public BaseResult addAccountAndRole(String account, String code, Integer type,String password) {
        if (org.springframework.util.StringUtils.isEmpty(account) || org.springframework.util.StringUtils.isEmpty(code)) {
            return new BaseResult(Constants.RESPONSE_CODE_400, Constants.RESPONSE_MESSAGE_400);
        }
//      查询code对应的角色
        Role role = new Role().selectOne(new EntityWrapper<Role>().eq("code", code).eq("type", type).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        if (role == null) {
            return new BaseResult(Constants.RESPONSE_CODE_602, "code：" + code + "，不存在，请先增加code对应的角色");
        }
//      校验账户是否已经注册
        AccountInfo preAccount = new AccountInfo().selectOne(new EntityWrapper<AccountInfo>().eq(AccountConstants.ACCOUNT_FIELD, account).eq("type", 2).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        if (preAccount != null) {
//          校验用户状态
            if (AccountConstants.ENABLE_FALSE.equals(preAccount.getEnable())) {
                return new BaseResult(Constants.RESPONSE_CODE_401, "您的账户已经被停用，请联系管理员");
            }
            String accountId = preAccount.getId();
//          查询用户角色
            Map<String, Object> map = new HashMap<>();
            map.put("accountId", accountId);
            map.put("type", "0");
            map.put("logicDelete", Constants.DEL_LOGIC_NORMAL);
            List<RoleDto> roles = accountRoleMapper.getRoleByAccountId(map);
            int flag = 0;
            if (roles != null && roles.size() > 0) {
//              查看用户是否有code对应的角色
                for (RoleDto r : roles) {
                    if (!code.equals(r.getCode())) {
                        flag++;
                        distributeRole(role, accountId);
                    }
                }
                if (flag == 0) {
                    return new BaseResult(Constants.RESPONSE_CODE_601, "用户对应角色已存在");
                }
            } else {
//              给用户赋予角色
                distributeRole(role, accountId);
            }
            return new BaseResult(Constants.RESPONSE_CODE_200, Constants.RESPONSE_MESSAGE_200, accountId);
        } else {
//          新增用户
            AccountInfo a = new AccountInfo();
            a.setAccount(account);
            a.setSalt(Encrypt.generateSalt(10));
            a.setPassword(Encrypt.md5ForAuth(password, a.getSalt()));
            a.setEnable(AccountConstants.ENABLE_TRUE);
            a.setType(type);
            a.preInsert();
            a.insert();
//          给用户赋予权限
            distributeRole(role, a.getId());
            return new BaseResult(Constants.RESPONSE_CODE_200, Constants.RESPONSE_MESSAGE_200, a.getId());
        }
    }
    /**
     * 给用户赋予角色
     *
     * @param role
     * @param accountId
     */
    private void distributeRole(Role role, String accountId) {
        AccountRole accountRole = new AccountRole();
        accountRole.setType("0");
        accountRole.setAccountId(accountId);
        accountRole.setRoleId(role.getId());
        accountRole.setLogicDelete(Constants.DEL_LOGIC_NORMAL);
        accountRole.preInsert();
        accountRole.insert();
    }
}
